import type { IconId } from '../../../lib/icons/types/interfaces'
import type { PlatformElementConfig } from '../../../types/interfaces'
import { BaseModule } from '../../../lib/abstract'
import { IconService } from '../../../lib/icons'
import { MarkElement } from '../../../lib/mark_element'
import { PageHandler } from '../../../lib/page_handler'
import { GooglePage } from '../../../lib/page_handler/platform/google'
import {
  GOOGLE_HEADER_USER_CENTER_SELECTOR,
  GOOGLE_VIDEO_PAGE_SEARCH_TIP_SELECTOR,
  GooglePageType,
} from '../../../lib/page_handler/platform/google/types'
import { ToolKit } from '../../../lib/utils/toolkit'
import {
  APP_DOM_SELECTOR_CONFIG,
  AppStyleCollections,
  BodyAttrs,
  getPlatformValue,
  HOSTNAME,
  logger,
  PAGE_ELEMENTS,
  REDIRECT_RULES,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'

interface Config {
  enabled?: boolean
}

export interface TitleConfig {
  allowedTitles: string[] // 允许的标题文本数组
  dataAttribute: string // 要设置的data属性名
  selector: string // 目标元素选择器
  logEnabled?: boolean // 是否启用日志
}

export interface LinkMatchPattern {
  urlMatcher: MatchPattern
}

export interface LinkProcessRule {
  id: IconId // 规则ID
  match: LinkMatchPattern // 匹配规则配置
  titlePattern?: RegExp // 可选：标题匹配规则
}

/**
 * 文章链接规则
 */
export const ARTICLE_LINK_RULES: LinkProcessRule[] = IconService.getInstance().api.icons.articleLink.map(icon => ({
  id: icon.id,
  match: {
    urlMatcher: icon.match?.link || '',
  },
}))

export class ElementAdapt extends BaseModule {
  readonly id: string = 'element_adapt'
  readonly name: string = 'ElementAdapt'
  readonly isInitialized: boolean = false
  readonly supportedPlatforms?: string[] | undefined
  private static instance: ElementAdapt
  private readonly pageHandler: PageHandler = PageHandler.getInstance()
  private readonly markElement: MarkElement = MarkElement.getInstance()
  readonly elements: Record<string, PlatformElementConfig> = PAGE_ELEMENTS[getPlatformValue(HOSTNAME) || ''] || {}

  config: Config = {
    enabled: true,
  }

  /**
   * 获取单例实例
   */
  public static getInstance(): ElementAdapt {
    if (!ElementAdapt.instance) {
      ElementAdapt.instance = new ElementAdapt()
    }
    return ElementAdapt.instance
  }

  destroy(): void {
    super.destroy()
  }

  core(): void {
    this.loadConfig()

    if (!this.config.enabled)
      return

    this.updateElementByPhase()
  }

  onToggleCallback(_id: string, _checked: boolean): void {
    super.onToggleCallback(_id, _checked)
  }

  setLoginStatus(): void {
    const $noLogin = $('#csdn-toolbar-profile-nologin')
    document.body.dataset.loginStatus = $noLogin.length > 0 ? 'no-login' : 'login'
  }

  /**
   * 通用文本处理函数
   * @param configs 标题配置数组
   * @param logger 日志记录器对象
   */
  processTextElements(configs: TitleConfig[], logger?: any): void {
    configs.forEach((config) => {
      const { allowedTitles, dataAttribute, selector, logEnabled = true } = config

      $(selector).each(function () {
        const $element = $(this)
        const textContent = $element.text().trim() // 获取清理后的文本内容

        if (allowedTitles.includes(textContent)) {
          $element.attr(dataAttribute, textContent)

          if (logEnabled && logger) {
            logger.checkpoint(`[元素] [${selector}] ${dataAttribute} 属性值设置为: ${textContent}`)
          }
        }
      })
    })
  }

  /**
   * 检查链接是否匹配规则
   * @param linkHref 链接的 href 属性值
   * @param rule 链接处理规则
   * @returns 是否匹配
   */
  isMatch(linkHref: string, rule: LinkProcessRule): boolean {
    const { urlMatcher } = rule.match

    return ToolKit.string.isMatch(linkHref, urlMatcher)
  }

  /**
   * 处理特殊链接
   * @param containerSelector 容器选择器（如 '#article-content'）
   * @param rules 链接处理规则（默认使用内置规则）
   */
  processSpecialLinks(
    containerSelector: string,
    rules: LinkProcessRule[] = ARTICLE_LINK_RULES,
  ): void {
    $(`${containerSelector} a[href^="http"]`).each((_index, element) => {
      const $link = $(element)
      let href = $link.attr('href') || ''
      const title = $link.attr('title') || $link.text().trim()

      // 1. 处理重定向链接
      try {
        const url = new URL(href)
        const matchedRule = REDIRECT_RULES.find(rule =>
          url.hostname.includes(rule.domain),
        )

        if (matchedRule) {
          const redirectUrl = url.searchParams.get(matchedRule.paramName || '')
          if (redirectUrl) {
            href = decodeURIComponent(redirectUrl) // 解码URL参数
          }
        }
      }
      catch (e) {
        logger.warn(`[${this.name}] 链接解析失败 ${href}`, e)
      }

      // 2. 检查匹配规则
      const matchedRule = rules.find((rule) => {
        const domainMatch = this.isMatch(href, rule)
        const titleMatch = rule.titlePattern ? rule.titlePattern.test(title) : true
        return domainMatch && titleMatch
      })

      if (matchedRule) {
        $link.attr(BodyAttrs.LINK_TYPE, matchedRule.id)
        // logger.debug(`[链接处理] 已标记 ${href} 为 ${matchedRule.attrValue}`)
      }
    })
  }

  /**
   * 更新元素信息
   */
  private updateBasicStructure(): void {}

  private updateContentElements(): void {
    const pageType = PageHandler.getCurrentPageType()

    if (HOSTNAME === SUPPORTED_PLATFORMS.CSDN) {
    // =============================== 【CSDN】 ===============================
      const TITLE_CONFIGS: TitleConfig[] = [
        {
          allowedTitles: ['大家在看', '热门文章'],
          dataAttribute: 'data-title',
          selector: '#asideHotArticle h3.aside-title',
          logEnabled: false,
        },
        {
          allowedTitles: ['最新文章'],
          dataAttribute: 'data-title',
          selector: '#asideArchive h3.aside-title',
          logEnabled: false,
        },
        {
          allowedTitles: ['分类专栏'],
          dataAttribute: 'data-title',
          selector: '.kind_person h3.aside-title',
          logEnabled: false,
        },
      ]

      this.processTextElements(TITLE_CONFIGS, logger)
      this.setLoginStatus()
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.JIAN_SHU) {
      // =============================== 【简书】 ===============================
      const $article = $('article')?.attr('data-page-element', 'article-container')
      const $articleWrapper = $article?.closest('section')
      $articleWrapper?.attr('data-page-element', 'content-container')
      $articleWrapper.find('> h1')?.attr('data-page-element', 'title-container')
      $articleWrapper.find('> div:has(span:contains("IP属地"))')?.attr('data-page-element', 'info-container')
      $articleWrapper.find('> div')?.filter((_index, el) => {
        const height = $(el).height()
        return height !== undefined && Math.round(height) === 1
      }).attr('data-page-element', 'page-separator')

      if (!$article?.length) {
        $('#__next > div > div').attr('data-page-element', 'empty-container')
      }
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.JUE_JIN) {
      // =============================== 【稀土掘金】 ===============================
      // 对平台用户自定义的引用元素进行标识处理，避免被主题样式覆盖
      $('blockquote').each(function () {
        const $blockquote = $(this)
        const beforeContent = ToolKit.ui.element.getPseudoContent($blockquote, 'before')
        const afterContent = ToolKit.ui.element.getPseudoContent($blockquote, 'after')

        // 检查是否匹配目标引号样式
        if (beforeContent === '"❝"' && afterContent === '"❞"') {
          ToolKit.browser.platform.markElement($blockquote, APP_DOM_SELECTOR_CONFIG.TEXT_CONTAINER.BLOCKQUOTE.value)
        }
      })
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.ZHI_HU) {
      // =============================== 【知乎】 ===============================
      ToolKit.async.delay(3000).then(() => {
        const $columnCard = $(`article > div:has(a:contains("所属专栏"))`)
        $columnCard.attr('data-page-element', 'column-card')
        $columnCard.find('div').each(function () {
          const $div = $(this)
          const hasHotContent = $div.contents().toArray().some(node =>
            node.nodeType === 3 // 文本节点
            && node.textContent?.trim().includes('最热内容'),
          )

          if (hasHotContent) {
            ToolKit.browser.platform.markElement($div.siblings().eq(0), 'column-card-hot-content')
          }
        })
        $columnCard.find('div').each(function () {
          const $div = $(this)
          const hasContentMeta = $div.contents().toArray().some(node =>
            node.nodeType === 3 // 文本节点
            && /篇内容.*赞同|赞同.*篇内容/.test(node.textContent?.trim() || ''),
          )

          if (hasContentMeta) {
            ToolKit.browser.platform.markElement($div.siblings().not('img').eq(0), 'column-card-author')
          }
        })
      },
      )
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.ZHI_HU_QUESTION) {
      // =============================== 【知乎问答】 ===============================
      const $eventContainer = $('.Question-main .Question-mainColumn .Card > div > div > a')

      ToolKit.browser.platform.markElement($eventContainer, AppStyleCollections.Event.WRAPPER)
      ToolKit.browser.platform.markElement($eventContainer.find('> div:has(svg)'), AppStyleCollections.Event.CONTAINER)
      ToolKit.browser.platform.markElement($eventContainer.find('> div:not(:has(svg))'), AppStyleCollections.Event.TIME)
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.BAI_DU) {
      // =============================== 【百度】 ===============================
      this.markElement.markBaiduElements(pageType)
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.SO_GOU) {
      // =============================== 【搜狗搜索】 ===============================
      const $searchResultItems = $(this.pageHandler.pages.sogou.getResultSelectors().selector)
      $searchResultItems.each((_index, item) => {
        const $item = $(item)
        if ($item.hasClass('reactResult')) {
          if ($item.find('.vrwrap > div[class^=movie-struct]').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.MOVIE,
            )
          }
          if ($item.find('span:contains("短剧热搜榜")').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.SHORT_VIDEO_HOT_LIST,
            )
          }
          if ($item.find('h3:contains("搜狗汉语")').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.SOGOU_CHINESE,
            )
          }
          if ($item.find('h3:contains("搜狗图片")').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.SOGOU_IMAGE,
            )
          }
          if ($item.find('a:contains("精选视频")').length && $item.find('ul[class^=video-list]').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.FEATURED_VIDEOS,
            )
          }
          if ($item.find('.analysis-steps__titleAiSearchIcon_bcda [class^=icon__logoText]').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Search.class.SEARCH_AI_ANSWER,
            )
          }
        }
        else if ($item.hasClass('vrwrap')) {
          if ($item.find('a[href*=\'baike.sogou.com\'], a:contains(\'搜狗百科\'), .more-box span:contains(\'搜狗百科\')').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.SOGOU_ENCYCLOPEDIA,
            )
          }
          if ($item.find('.fb cite:contains(\'搜狗问问\')').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.SOGOU_ASK,
            )
          }
          if ($item.find('h3:contains("搜狗下载") > a[href*=\'xiazai.sogou.com\']').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.SOGOU_DOWNLOAD,
            )
          }
          if ($item.find('h3:contains("相关资讯")').parent('[class*=zixun]').length) {
            ToolKit.browser.platform.markElement(
              $item,
              AppStyleCollections.Sogou.NEWS,
            )
          }
        }
      })
    }
    else if (HOSTNAME === SUPPORTED_PLATFORMS.GOOGLE) {
      // =============================== 【谷歌搜索】 ===============================
      const selectors = GooglePage.getInstance().getResultSelectors()
      const { selector } = selectors

      if ([GooglePageType.Index, GooglePageType.IndexHk].includes(pageType as GooglePageType)) {
        const $searchContainer = ToolKit.browser.platform.markElement(
          $('form[role=search]'),
          AppStyleCollections.Search.class.SEARCH_CONTAINER,
        )
        const $search = $searchContainer.find('> div > div[jscontroller]')

        ToolKit.browser.platform.markElement(
          $search.find('> div[jsname]:not([jscontroller])'),
          AppStyleCollections.Search.class.SEARCH_BOX,
        )
        ToolKit.browser.platform.markElement(
          $search.find('> div[jsname][jscontroller]'),
          AppStyleCollections.Search.class.SEARCH_HISTORY,
        )
      }

      // 添加用户中心标识类
      ToolKit.browser.platform.markElement(
        $(GOOGLE_HEADER_USER_CENTER_SELECTOR),
        AppStyleCollections.Search.class.SEARCH_HEADER_USER_CENTER,
      )

      if (!selector)
        return

      if ([GooglePageType.All, GooglePageType.Web].includes(pageType as GooglePageType)) {
        // 标识图片结果
        ToolKit.browser.platform.markElement(
          $(selector).has('[role="heading"] > span:contains("图片")').has('span:contains("显示更多图片")'),
          AppStyleCollections.Search.class.SEARCH_ITEM_IMAGE,
        )
        // 标识结果链接
        ToolKit.browser.platform.markElement(
          $(selector).find('h3').siblings('div').addClass(AppStyleCollections.Google.LINK_CONTAINER).find('div:has(> cite)'),
          AppStyleCollections.Google.LINK,
        )
        // 标识结果链接详细按钮
        ToolKit.browser.platform.markElement(
          $(selector).find('h3').closest('span').siblings('div'),
          AppStyleCollections.Google.LINK_DETAIL_BUTTON,
        )
        // 标识大家还在搜
        ToolKit.browser.platform.markElement(
          $(selector).has('[role="heading"]:contains("用户还搜索了")'),
          AppStyleCollections.Search.class.SIMILAR_SIMILAR_QUERIES,
        )
      }
      else if (pageType === GooglePageType.Video) {
        // 标识搜索提示
        ToolKit.browser.platform.markElement(
          $(GOOGLE_VIDEO_PAGE_SEARCH_TIP_SELECTOR).has('div.card-section:contains("小提示")'),
          AppStyleCollections.Search.class.SEARCH_TIP,
        )
        // 标识结果链接
        ToolKit.browser.platform.markElement(
          $(selector).find('h3 + div:has(cite)'),
          AppStyleCollections.Google.LINK,
        )
        // 标识结果链接详细按钮
        ToolKit.browser.platform.markElement(
          $(selector).find('h3').closest('span').siblings('div'),
          AppStyleCollections.Google.LINK_DETAIL_BUTTON,
        )
      }
      else if (pageType === GooglePageType.Books) {
        // 标识结果链接容器
        ToolKit.browser.platform.markElement(
          $(selector).find('h3 + div:has(cite)'),
          AppStyleCollections.Google.LINK,
        )
      }
      else if (pageType === GooglePageType.News) {
        // 标识结果链接容器
        ToolKit.browser.platform.markElement(
          $(selector).find('[role="heading"]').siblings('div:has(img)'),
          AppStyleCollections.Google.LINK_CONTAINER,
        )
      }
    }

    // 更新文章链接
    const { ARTICLE_CONTAINER } = this.elements

    if (!ARTICLE_CONTAINER || !ARTICLE_CONTAINER.selector)
      return

    this.processSpecialLinks(ARTICLE_CONTAINER.selector)
  }

  private updateLazyLoadedElements(): void {}

  /**
   * 分阶段更新元素
   */
  updateElementByPhase(force: boolean = false): void {
    if (force) {
      this.updateBasicStructure()
      this.updateContentElements()
      this.updateLazyLoadedElements()
      return
    }

    // 第一阶段：body 可用时执行
    ToolKit.async.whenDomReady(() => {
      this.updateBasicStructure()
    }, { phase: 'document-body' })

    // 第二阶段：DOM 完全加载后执行
    ToolKit.async.whenDomReady(() => {
      this.updateContentElements()
    }, { phase: 'document-end' })

    // 第三阶段：网络空闲时执行
    ToolKit.async.whenDomReady(() => {
      this.updateLazyLoadedElements()
    }, { phase: 'network-idle' })
  }

  applyConfig(config: Partial<Config>): void {
    super.updateConfig(config)
    this.updateElementByPhase()
    logger.info(`[${this.name}] Config updated and apply`, this.config)
  }
}
